<?php

/**
 *      This is NOT a freeware, use is subject to license terms
 *      应用名称: 平安通用支付模块 免费版2.0.4
 *      下载地址: https://addon.dismall.com/plugins/boan_payment.html
 *      应用开发者: 平安网络科技
 *      开发者QQ: 527340870
 *      更新日期: 202306240040
 *      授权域名: www.nx520.cn
 *      授权码: 2023030110f0cZTsZOtz
 *      未经应用程序开发者/所有者的书面许可，不得进行反向工程、反向汇编、反向编译等，不得擅自复制、修改、链接、转载、汇编、发表、出版、发展与之有关的衍生产品、作品等
 */

if (!defined('IN_DISCUZ')) {
    exit('Access denid');
}
define('P_PAYMENT', 'plugin/boan_payment');
require_once dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'common.inc.php';
class model_payment{
    
    var $order_id = '';
    var $vars = '';
    private $pluginObj;
    
    private function loadPlugin($identifier){
        $classname = $identifier.'_payment';
       
        if(!class_exists($classname)){
            $file = DISCUZ_ROOT.'/source/plugin/'.$identifier.'/'.$identifier.'_payment.php';
          
            if(!file_exists($file)){
                return 0;
            }
            require_once  $file;
        }
        $this->pluginObj = new $classname;
        return 1;
    }
    
    function __construct(){
        global $_G;
        
        if(empty($_G['cache']['plugin'])){
            loadcache('plugin');
        }
        $this->vars = $_G['cache']['plugin']['boan_payment'];
    }
    
    
    function setOrder($order_id){
        $this->order =  C::t('#boan_payment#boan_payment_order')->fetch($order_id);
        return !empty($this->order); 
    }
    
    function getOrder($order_id,$force_from_db = false){
        return C::t('#boan_payment#boan_payment_order')->fetch($order_id,$force_from_db);
    }
    
    function isPay($order_id){
        $order = $this->getOrder($order_id,true);
        return !empty($order) && $order['status'] == 0;
    }
    
    function isActivation($pay_method){
        
        return $this->vars[$pay_method.'_ok'];
    }
    
    
    function checkPay($order_id,$pay_method){
        
        $order = $this->getOrder($order_id,true);
        if(empty($order)){
            return 0;
        }
        if($order['status'] == 1){
            return 1;
        }
        
        if(!$this->isActivation($pay_method)){
            return 0;
        }
        
        boan_loadPayMethod($pay_method);
        
        $pay = new $pay_method;
        
        return $pay->Query($order_id);
    }
    
    
    function createOrder($identifier,$subject,$amount,$body = '',$return_url = '',$expire = 86400,$params = '',$uid = ''){
        global $_G;
        empty($uid) && $uid = $_G['uid'];
        if(empty($uid)){
            throw new Exception(lang(P_PAYMENT, 'nologin'));
        }
        $amount = floatval($amount);
        if(empty($subject) || empty($amount)){
            throw new Exception(lang(P_PAYMENT, 'order_err1'));
        }
        
        if($amount < 0){
            throw new Exception(lang(P_PAYMENT, 'order_err2'));
        }
        
        if(!$this->loadPlugin($identifier)){
            throw new Exception(lang(P_PAYMENT, 'plugin_err1'));
        }
        
        $subject = dhtmlspecialchars($subject);
        $body= dhtmlspecialchars($body);
        do{
            $order_id = date('YmdHis',TIMESTAMP).random(10,1);
        } while(!empty(DB::fetch_first('SELECT * FROM %t WHERE order_id=%s',array('boan_payment_order',$order_id))));
        
        $username = getuserbyuid($uid);
        $username = $username['username'];
        
        $plugin_name = C::t('common_plugin')->fetch_by_identifier($identifier);
        $plugin_name = $plugin_name['name'];
        
        $data['order_id'] = $order_id;
        
        $data['subject'] = $subject;
        $data['body'] = $body;
        $data['amount'] = $amount;
        $data['uid'] = $uid;
        $data['username'] = $username;
        $data['create_time'] = TIMESTAMP;
        $data['expire_time'] = TIMESTAMP + $expire;
        $data['status'] = 0;
        $data['plugin_notify'] = 0;
        $data['identifier'] = $identifier;
        $data['plugin_name'] =  $plugin_name;
        $data['return_url'] = $return_url;
        $data['params'] = serialize($params);
     
        if(C::t('#boan_payment#boan_payment_order')->insert($data)){
            $this->log($order_id, 1, 'create_order','['.$username.']'.lang(P_PAYMENT, 'order_info2'),2,'',$identifier);
            return $order_id;
        }else{
            throw new Exception(lang(P_PAYMENT, 'order_err3'));
        }
    }
    
    function updateOrder($order_id,$data){
        return C::t('#boan_payment#boan_payment_order')->update($order_id,$data);
    }
    
    function deleteOrder($order_id){
        $order = $this->getOrder($order_id);
        if(!empty($order) && $order['status'] == 0 && $order['expire_time'] < TIMESTAMP){
            return C::t('#boan_payment#boan_payment_order')->delete($order_id);
        }
        return 0;
    }
    
    function pluginNotify($order_id,$method){
       $order = $this->getOrder($order_id,true);
       if(empty($order)){
           throw new Exception(lang(P_PAYMENT, 'order_err4'));
       }
       
       if(empty($order['identifier']) || !$this->loadPlugin($order['identifier'])){
           throw new Exception(lang(P_PAYMENT, 'plugin_err1'));
       }
      
       if($order['plugin_notify'] != 1 && method_exists($this->pluginObj, $method)){
           $order['params'] = unserialize($order['params']);
           if($this->pluginObj->$method($order)){
               $this->updateOrder($order_id, ['plugin_notify' => 1]);
               return ;
           }
       }
       $this->updateOrder($order_id, ['plugin_notify' => 2]);
    }
    
    function verify($pay_method,$arr){
       
        boan_loadPayMethod($pay_method);
        
        $pay = new $pay_method;
        
        return $pay->verify($arr);
    }
    
    
    function getPayUrl($order_id,$pay_method,$is_qrcode = 1,$qrcode_width = 0){
        global $_G; 
        if($is_qrcode){
           $order = $this->getOrder($order_id);
           if(empty($order)){
               throw new Exception(lang(P_PAYMENT, 'order_err4'));
           }
           if($order['expire_time'] < TIMESTAMP){
               throw new Exception(lang(P_PAYMENT, 'order_err5'));
           }
           
           if($order['status'] > 0){
               throw new Exception(lang(P_PAYMENT, 'order_err6'));
           }
           
           if(!boan_loadPayMethod($pay_method)){
               throw new Exception(lang(P_PAYMENT, 'pay_err1'));
           }
           $pay = new $pay_method;
          
           if(!$pay->isActivation()){
               throw new Exception($pay_method == 'alipay' ? lang(P_PAYMENT, 'pay_err2') : lang(P_PAYMENT, 'pay_err3'));
           }
           
           $biz_content = [
               'out_trade_no' => $order['order_id'],
               'total_amount' => $order['amount'],
               'subject' => cutstr($order['subject'],80),
               'body' => $order['body'],
           ];
           $url = $pay->getQrcode($biz_content);
           if(empty($url)){
               return '';
           }
           if(defined('IN_MOBILE') && $pay_method == 'alipay'){
               header('location:'.$url);
           }
           
           $url = urlencode($url);
       }
        return 'plugin.php?id=boan_payment:pay&order_id='.$order_id.'&pay_method='.$pay_method.'&qrcode='.($is_qrcode ? $url : '').'&qrcode_width='.$qrcode_width;
    }
    
    
    function makePay(){
        global $_G;
        $vars = $_G['cache']['plugin']['boan_payment'];
       
       
         $order_id = dhtmlspecialchars($_GET['order_id']);
         $order = $this->getOrder($order_id);
         if(empty($order)){
             throw new Exception(lang(P_PAYMENT, 'order_err4'));
         }
         if($order['expire_time'] < TIMESTAMP){
             throw new Exception(lang(P_PAYMENT, 'order_err5'));
         }
         
         if($order['status'] > 0){
             throw new Exception(lang(P_PAYMENT, 'order_err6'));
         }
         
         $pay_method = dhtmlspecialchars($_GET['pay_method']);
         
         if(!boan_loadPayMethod($pay_method)){
             throw new Exception(lang(P_PAYMENT, 'pay_err1'));
         }
         $pay = new $pay_method;
        
         if(!$pay->isActivation()){
             throw new Exception(lang(P_PAYMENT, 'pay_err2'));
         }
         $biz_content = [
             'out_trade_no' => $order['order_id'],
             'total_amount' => $order['amount'],
             'subject' => cutstr($order['subject'],80),
             'body' => $order['body'],
         ];
         
         if($_GET['qrcode']){
             if (!class_exists('QRcode')) {
              require_once DISCUZ_ROOT.'source/plugin/boan_payment/phpqrcode.php'; 
             }
             $size = 5;
             $url = $_GET['qrcode'];
          
             if($vars['hpjpay_ok'] && $pay_method == 'wxpay' || $vars['hpjpay_alipay_ok'] && $pay_method == 'alipay'){
                 header('location:'.$url);
             }
             
             if($_GET['qrcode_width']){
                 $size = intval(intval($_GET['qrcode_width']) / 29);
             }
            
             if($vars['logo_url'] && ($logo = dfsockopen(($vars['logo_url'])))){
                 $tmpfilename =$_G['setting']['attachdir'].'temp/'.random(16).'.png';
                 QRcode::png($url, $tmpfilename, QR_ECLEVEL_H, $size, 0);
              
                 $QR = imagecreatefromstring(file_get_contents($tmpfilename));
                 $logo = imagecreatefromstring($logo);
                 $QR_width = imagesx($QR);
                 $QR_height = imagesy($QR);
                 $logo_width = imagesx($logo);
                 $logo_height = imagesy($logo);
                 
                 $logo_qr_width = $QR_width /4;
                 $scale = $logo_width/$logo_qr_width;
                 $logo_qr_height = $logo_height/$scale;
                 
                 $from_width = ($QR_width - $logo_qr_width)/2;
                 imagecopyresampled($QR, $logo, $from_width,$from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);
            
                 @unlink($tmpfilename);
                 
                 dheader('Content-type: image/png');
                 imagepng($QR);
                 imagedestroy($QR);
                 imagedestroy($logo);
                 
             }else{
                 QRcode::png($url, false, QR_ECLEVEL_L, $size, 0);
             }
             exit();
         }
         
         if(checkmobile()){
             header('location:'.$pay->getWap($biz_content));
             exit();
         }
         
         
         dheader('location:'.$pay->getPage($biz_content));
    }
    
    /**
     * 
     * @param unknown $order_id
     * @param unknown $level      级别：1=系统级错误(PHP执行错误)  2=支付级消息  3=插件级消息      
     * @param unknown $subject    通知标题,如果是支付级消息此处应该是支付接口名称
     * @param unknown $message    详细信息
     * @param unknown $type       1=出错通知  2=普通通知
     * @param string $return_info 如果是支付级错误，此处填写支付平台的返回值(会自动序列化)
     * @param string $identifier  插件级信息填写此处
     */
    function log($order_id,$level,$subject,$message,$type = 1,$return_info = '',$identifier = ''){
       
        if(!empty($order_id) && empty($identifier)){
           $order = $this->getOrder($order_id);
           if(!empty($order)){
              $identifier = $order['identifier'];
           }
        }
        $data = [
            'order_id' => $order_id,
            'level' => $level,
            'subject' => $subject,
            'message' => $message,
            'type' => $type,
            'return_info' => empty($return_info) ? '' : serialize(boan_paymentBase::iconv($return_info,'utf-8',CHARSET)),
            'identifier' => $identifier,
            'create_time' => TIMESTAMP,
        ];
       C::t('#boan_payment#boan_payment_log')->insert_log($data);
    }
    
    function test(){
    }
         
}

